# amplitude.lib.date -- Date class

from amplitude.dict import Dict
import datetime

class Date(Dict):
    """defines a date that can have any of year, month, day -- it can be ambiguous.
    Usage:
    >>> d = Date(20091027)
    >>> "{Y}-{m}-{d}".format(**d)           # new in Python 2.6: string.format()
    '2009-10-27'
    >>> d.year(2008), d.month(9), d.day(6)
    (2008, 9, 6)
    >>> "{b} {d}, {Y}".format(**d)
    'Sep 6, 2008'
    >>> "{B} {d}".format(**d)
    'September 6'
    >>> "{Y}-{m:02}-{d:02}".format(**d)     # note the format specifiers
    '2008-09-06'
    >>> d = Date(814)              # month and day only -- such as birthday
    >>> "{Y} {b} {d}".format(**d)
    '0 Aug 14'
    >>> d.Y
    0
    """
    
    def __init__(self, date=None, locale='en'):
        """date: integer in form of [[yyyy]mm]dd"""
        self._locale = locale
        self.date(date or 0, locale)

    def date(self, date=None, locale='en'):
        if date is not None:
            self._date = int(date)
            self._locale = locale
            d = {
                'Y': self.year() != 0 and str(self.year()) or '',
                'y': self.year() != 0 and str(int(self.year() % 100)) or '',
                'm': self.month() != 0 and str(self.month()) or '',
                'd': self.day() != 0 and str(self.day()) or '',
                'B': self.month_name() or '',
                'b': self.mo_name() or ''
            }
            for k in d.keys():
                self[k] = d[k]
        return self._date

    def year(self, yr=None):
        if yr is not None:
            self.date(yr*1e4 + (self.month() or 0)*1e2 + (self.day() or 0))
        if self._date is not None:
            return int(self.date() / 1e4)

    def month(self, mo=None):
        if mo is not None:
            self.date((self.year()*1e4 or 0) + mo*1e2 + (self.day() or 0))
        if self._date is not None:
            return int(self.date() % 1e4 / 1e2)
        
    def day(self, dy=None):
        if dy is not None:
            self.date((self.year()*1e4 or 0) + (self.month()*1e2 or 0) + dy)
        if self._date is not None:
            return int(self.date() % 1e2)

    def month_name(self):
        return self.months()[self.month()]
        
    def mo_name(self):
        return self.mos()[self.month()]

    def months(self):
        """returns a list of months, indexed 1..12, for given locale."""
        return eval("self.months_%s()" % self._locale)
        
    def months_en(self):
        return [None, 'January', 'February', 'March', 'April', 'May', 'June',
                'July', 'August', 'September', 'October', 'November', 'December']

    def mos(self):
        """returns a list of months, indexed 1..12, for given locale."""
        return eval("self.mos_%s()" % self._locale)
        
    def mos_en(self):
        return [None, 'Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'June',
                'July', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.']

    def __str__(self):
        return str(int(self.date()))

    def format(self):
        s = u''
        if self.month() != 0:
            s += self.mo_name()
            if self.day() != 0:
                s += " %d" % self.day()
                if self.year() != 0:
                    s += ','
        if self.year() != 0:
            if s != '': s += ' '
            s += str(self.year())
        return s

    def form_field(self, prefix=None, start_year=1900):
        s="<!-- %s -->" % prefix.upper()
        # MONTH
        s+="""<select name="%smonth"><option value=''></option>""" % prefix
        for i in range(1, len(self.mos())):
            if self.month() == i:
                s+="""<option value=%d selected>%s</option>""" % (i, self.mos()[i] or '')
            else:
                s+="""<option value=%d>%s</option>""" % (i, self.mos()[i] or '')
        s+="</select>"
        # DAY
        s+="""<select name="%sday"><option value=''></option>""" % prefix
        for i in range(1, 31+1):
            if self.day() == i:
                s+="""<option value=%d selected>%d</option>""" % (i, i)
            else:
                s+="""<option value=%d>%d</option>""" % (i, i)
        s+="""</select>"""
        # YEAR
        s+="""<select name="%syear"><option value=''></option>""" % prefix
        for i in range(start_year, datetime.date.today().year+1):
            if self.year() == i:
                s+="""<option value=%d selected>%d</option>""" % (i, i)
            else:
                s+="""<option value=%d>%d</option>""" % (i, i)
        s+="""</select>"""
        s+="""<!-- END %s -->""" % prefix.upper()
        return s

    def process_params(self, prefix='', **params):
        """take attributes given for month, day, and year, and create date."""
        if params.has_key("%syear" % prefix):
            yr = params.get("%syear" % prefix)
            if yr is not None:
                if yr == '': yr = 0
                self.year(int(yr))
        if params.has_key("%smonth" % prefix):
            mo = params.get("%smonth" % prefix)
            if mo is not None:
                if mo == '': mo = 0
                self.month(int(mo))
        if params.has_key("%sday" % prefix):
            dy = params.get("%sday" % prefix)
            if dy is not None:
                if dy == '': dy = 0
                self.day(int(dy))
        return self.date()


if __name__ == "__main__":
    import doctest
    doctest.testmod()
